package com.zzedu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zzedu.common.core.domain.entity.SysRole;
import com.zzedu.common.core.domain.entity.SysUser;
import com.zzedu.common.enums.UserTypeEnumns;
import com.zzedu.system.domain.SysUserRole;
import com.zzedu.system.mapper.SysUserMapper;
import com.zzedu.system.service.ISysDeptService;
import com.zzedu.system.service.ISysRoleService;
import com.zzedu.system.service.ISysUserRoleService;
import com.zzedu.system.service.ISysUserService;
import org.apache.commons.collections4.MapUtils;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户 业务层处理
 *
 * @author smarthome
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Autowired
    ISysRoleService sysRoleService;

    @Autowired
    ISysUserRoleService sysUserRoleService;

    @Autowired
    ISysDeptService sysDeptService;

    @Override
    public IPage<SysUser> selectUserList(IPage<SysUser> page, SysUser user) {
        LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery(SysUser.class);
        queryWrapper.eq(null != user.getId(), SysUser::getId, user.getId());
        queryWrapper.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());
        queryWrapper.eq(null != user.getStatus(), SysUser::getStatus, user.getStatus());
        queryWrapper.like(StringUtils.isNotBlank(user.getPhoneNumber()), SysUser::getPhoneNumber, user.getPhoneNumber());
        queryWrapper.apply(null != user.getDeptId(), "(dept_id={0} or dept_id in(SELECT t.id FROM sys_dept t WHERE find_in_set({1}, ancestors)))", user.getDeptId(), user.getDeptId());
        Map map = user.getParams();
        if (!MapUtils.isEmpty(map)) {
            if (map.containsKey("beginTime")) {
                queryWrapper.ge(SysUser::getGmtCreate, MapUtils.getString(map, "beginTime"));
            }
            if (map.containsKey("endTime")) {
                queryWrapper.le(SysUser::getGmtCreate, MapUtils.getString(map, "endTime"));
            }
        }
        queryWrapper.orderByDesc(SysUser::getId);
        page.setRecords(Lists.newArrayList());
        this.baseMapper.selectList(page, queryWrapper, new ResultHandler<SysUser>() {
            @Override
            public void handleResult(ResultContext<? extends SysUser> resultContext) {
                SysUser sysUser = resultContext.getResultObject();
                if (null != sysUser.getDeptId()) {
                    sysUser.setDept(sysDeptService.getById(sysUser.getDeptId()));
                }
                page.getRecords().add(sysUser);
            }
        });
        return page;
    }

    public IPage<SysUser> selectAllocatedList(SysUser user) {
        LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery(SysUser.class);
        queryWrapper.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());
        queryWrapper.eq(null != user.getStatus(), SysUser::getStatus, user.getStatus());
        queryWrapper.like(StringUtils.isNotBlank(user.getPhoneNumber()), SysUser::getPhoneNumber, user.getPhoneNumber());
        queryWrapper.apply("dept_id in(SELECT id FROM sys_dept WHERE deleted=0)");
        queryWrapper.apply("id in(SELECT user_id FROM sys_user_role WHERE deleted=0 and role_id in(select id from sys_role where deleted=0 and id={0}) )", user.getRoleId());
        return this.page(user.getPageDTO(), queryWrapper);
    }

    public IPage<SysUser> selectUnallocatedList(SysUser user) {
        LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery(SysUser.class);
        queryWrapper.eq(null != user.getId(), SysUser::getId, user.getId());
        queryWrapper.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());
        queryWrapper.eq(null != user.getStatus(), SysUser::getStatus, user.getStatus());
        queryWrapper.like(StringUtils.isNotBlank(user.getPhoneNumber()), SysUser::getPhoneNumber, user.getPhoneNumber());
        queryWrapper.apply("dept_id in(SELECT id FROM sys_dept WHERE deleted=0)");
        queryWrapper.apply("id not in(SELECT user_id FROM sys_user_role WHERE deleted=0 and role_id in(select id from sys_role where deleted=0 and id={0}) )", user.getRoleId());
        return this.page(user.getPageDTO(), queryWrapper);
    }

    /**
     * 通过用户名查询用户
     *
     * @param userName 用户名
     * @return 用户对象信息
     */
    public SysUser selectUserByUserName(String userName, UserTypeEnumns userTypeEnumns) {
        LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery(SysUser.class);
        queryWrapper.eq(SysUser::getUserName, userName);
        queryWrapper.eq(SysUser::getUserType, userTypeEnumns.getCode());
        queryWrapper.apply("dept_id in(select id FROM sys_dept where deleted=0)");
        queryWrapper.apply("id in(select user_id FROM sys_user_role where deleted=0 and role_id in(select id from sys_role where deleted=0))");
        queryWrapper.last("limit 1 ");
        return getOne(queryWrapper);
    }

    public SysUser selectUserById(Long userId) {
        return getById(userId);
    }


    /**
     * 根据用户ID查询用户所属角色组
     *
     * @param userName 用户名
     * @return 结果
     */
    public String selectUserRoleGroup(Long userId) {
        LambdaQueryWrapper<SysRole> lambdaQueryWrapper = Wrappers.lambdaQuery(SysRole.class);
        lambdaQueryWrapper.apply("id in(select role_id from sys_user_role where deleted=0 and user_id={0})", userId);
        List<SysRole> list = this.sysRoleService.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return "";
        }
        return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
    }

    @Override
    @Transactional
    public void insertUserAuth(Long userId, Long[] roleIds) {
        sysUserRoleService.remove(Wrappers.lambdaQuery(SysUserRole.class).eq(SysUserRole::getUserId, userId));
        for (Long id : roleIds) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(id);
            sysUserRoleService.save(sysUserRole);
        }
    }
}
